package org.itboys.mobile.service.mysql.weixin.pay;

import org.apache.commons.lang3.StringUtils;
import org.itboys.commons.ErrorException;
import org.itboys.commons.utils.tools.ListUtil;
import org.itboys.mobile.common.SundayCommonConstants;
import org.itboys.mobile.dao.order.CooOrderMapper;
import org.itboys.mobile.dao.order.CooOrderProductMapper;
import org.itboys.mobile.dao.wallet.CooWalletRecordMapper;
import org.itboys.mobile.dto.member.SundayWeixinMemberDto;
import org.itboys.mobile.entity.mysql.order.CooOrder;
import org.itboys.mobile.entity.mysql.order.CooOrderProduct;
import org.itboys.mobile.entity.mysql.pay.SundayPay;
import org.itboys.mobile.entity.mysql.pay.SundayPayConfig;
import org.itboys.mobile.entity.mysql.product.SundayProduct;
import org.itboys.mobile.entity.mysql.wallet.CooWallet;
import org.itboys.mobile.entity.mysql.wallet.CooWalletRecord;
import org.itboys.mobile.service.mysql.web.product.SundayProductService;
import org.itboys.mobile.service.mysql.weixin.wallet.CooWeixinWalletService;
import org.itboys.mobile.util.HttpRequestUtil;
import org.itboys.mobile.util.NumberUtil;
import org.itboys.mongodb.service.BaseMySqlService;
import org.itboys.pay.tools.XMLUtil;
import org.itboys.pay.weixin.JsPaySignTool;
import org.itboys.pay.weixin.WXPayNotify;
import org.itboys.pay.weixin.WeixinPayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.DataInputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * 作者：zzq
 * 时间：2017/12/7
 * 描述：迈迪龙_微信_支付
 */
@Service
public class SundayWeixinPayService extends BaseMySqlService<SundayPay> {
    public static String PAY_CALLBACK_URL_wechat= "http://xzbadmin.whitecao.cn/sunday/weixin/pay/callback/wechat";
    @Autowired
    private SundayWeiXinPayConfigService payConfigService;
    @Autowired
    private CooOrderMapper orderMapper;
    @Autowired
    private CooWeixinWalletService walletService;
    @Autowired
    private CooWalletRecordMapper walletRecordMapper;
    @Autowired
    private CooOrderProductMapper orderProductMapper;
    @Autowired
    private SundayProductService productService;

    /**
     * 支付页面
     * @param orderIds
     * @return
     */
    public Map<String, Object> index(List<Long> orderIds,Long memberId) {
        Map<String, Object> result = new HashMap<String, Object>();
        //传入第三方的外部订单号
        String orderNo = NumberUtil.generateNumber("PREPAY");
        StringBuilder orderIdsStr = new StringBuilder();
        StringBuilder chargeIdsStr = new StringBuilder();

        Map<String, Object> param = new HashMap<String, Object>();
        param.put("ids", orderIds);
        List<CooOrder> orders = orderMapper.select(param);
        //订单消费金额。
        Double payAmount = 0.00;
        for (CooOrder order : orders) {
            payAmount += order.getPayAmount().doubleValue();
        }
        for (Long orderId : orderIds) {
            //orderIdsLong.add(Long.valueOf(orderId));
            //实际写入预支付表的中的订单ID。实际在订单中查找拼接。此处是临时代码
            orderIdsStr.append(orderId + "_");

            CooWallet wallet=walletService.findByMemberId(memberId);
            CooWalletRecord walletRecord=new CooWalletRecord( memberId,  wallet.getId(), SundayCommonConstants.wallet_record_type_charge, "新坐标充值-未支付", wallet.getAbleLimit(),new BigDecimal(payAmount), SundayCommonConstants.NO);
            walletRecordMapper.insert(walletRecord);
            //存放需要充值记录ID时，用_隔开;
            chargeIdsStr.append(walletRecord.getId()+"_");

        }
        SundayPay sundayPay = new SundayPay(orderNo,orderIdsStr.substring(0,orderIdsStr.length()-1).toString(),chargeIdsStr.substring(0,chargeIdsStr.length()-1).toString(),
                new BigDecimal(payAmount).setScale(2,BigDecimal.ROUND_HALF_UP), null,"新坐标-在线购物充值");
        super.insert(sundayPay);
        result.put("orderNo", orderNo);
        result.put("payAmount", new BigDecimal(payAmount).setScale(2,BigDecimal.ROUND_HALF_UP));

        return result;
    }

    /**
     * 向微信发起统一下单请求
     * @param request
     * @param outTradeNo
     * @return
     * @throws Exception
     */
    //public  JsPaySignTool paySign(HttpServletRequest request,String outTradeNo) throws Exception {//获取预支付的信息
    public JsPaySignTool wechat_paySign(HttpServletRequest request, String outTradeNo) throws Exception{
        if(StringUtils.isEmpty(outTradeNo)){
            logger.error("未获取到预支付订单号");
            throw new ErrorException("未获取到预支付订单号");
        }
        Map<String,Object> param1 = new HashMap<String,Object>();
        param1.put("orderNo",outTradeNo);
        List<SundayPay> sundayPays=super.select(param1);
        SundayPay sundayPay = null;

        if(ListUtil.isNotNull(sundayPays)){
            sundayPay=sundayPays.get(0);
        }else{
            logger.error("订单编号:"+outTradeNo+"未找到对应的预支付记录");
            throw new ErrorException("订单编号:"+outTradeNo+"未找到对应的预支付记录");
        }

        //获取用户的htmlId
        SundayWeixinMemberDto member= HttpRequestUtil.getUser(request);
        BigDecimal payAmount=sundayPay.getPayAmount();
        //获取微信配置参数
        SundayPayConfig payConfig =  payConfigService.getPayConfig(SundayCommonConstants.pay_type_wechatpay_html);
            //微信支付的金额单位是分。
            String payAmountStr=String.valueOf(new BigDecimal(payAmount.doubleValue()*100).setScale(0,BigDecimal.ROUND_HALF_UP));



            //统一下单
            JsPaySignTool tool=	WeixinPayUtils.jsPay(
                    payConfig.getWeChatAppId(),
                    payConfig.getWeChatMchId(),
                    member.getWeixinOpenId(),
                    outTradeNo, 	"120.27.211.150",
                    sundayPay.getRemark(), payAmountStr,PAY_CALLBACK_URL_wechat, payConfig.getWeChatApi());


        return tool;
    }


    //微信回掉接口
    public String callback_wechat(HttpServletRequest request) throws Exception{


        String callback_wechat_msg="success";
        //1，检验签名和请求来源
        DataInputStream in = new DataInputStream(request.getInputStream());
        byte[] dataOrigin = new byte[request.getContentLength()];
        in.readFully(dataOrigin); // 根据长度，将消息实体的内容读入字节数组dataOrigin中
        if(null != in){
            in.close(); // 关闭数据流
        }
        String wxNotifyXml = new String(dataOrigin);
        Map<String, String> params = XMLUtil.doXMLParse(wxNotifyXml);
        logger.info("00000---------callback_wechat--------开始-----");
        for (String key : params.keySet()) {
            logger.info("------微信html回掉返回的参数key = " + key + " and ---------value = " + params.get(key));
        }
        logger.info("00000---------callback_wechat--------结束-----");
        //
        //微信配置信息
        SundayPayConfig payConfig =payConfigService.getPayConfig(SundayCommonConstants.pay_type_wechatpay_html);
        //微信API
        String wechatApi = payConfig.getWeChatApi();
        //校验签名
        boolean isSign= WXPayNotify.verifyNotify(params,wechatApi);
        logger.info("-------------------微信-html-回掉-签名校验实际结果--"+isSign);
        //2017年6月14日，零时不校验签名
        //isSign=true;
        if(!isSign){
            logger.error("支付微信-html-回掉-签名验证失败。");
            return "fail";
        }


        String  trade_status=params.get("result_code");
        String  out_trade_no=params.get("out_trade_no");
        String trade_no = params.get("transaction_id");

        //微信返回的是分(金融单位)
        String  total_fee =params.get("total_fee");
        logger.info("支付-微信-html-回掉-信息.trade_status="+trade_status+
                ",out_trade_no="+out_trade_no+
                ",trade_no="+trade_no+
                ",total_fee="+total_fee
        );

        Map<String,Object> param =new HashMap<String,Object>();
        //查询本地预支付记录
        param.clear();
        if(StringUtils.isEmpty(out_trade_no)){
            logger.error("支付-微信-html-回掉-外部订单为空");
            return "fail";
        }
        param.put("orderNo",out_trade_no);
        List<SundayPay> sundayPays = super.select(param);
        if(ListUtil.isNull(sundayPays)){
            logger.error("支付-微信-html-回掉-本地无预支付记录，返回");
            return "fail";
        }
        SundayPay pay=sundayPays.get(0);
        //2，项目内部逻辑。校验支付金额
        //校验付款金额。微信返回的是分（金额单位）
        BigDecimal paidAmount=new BigDecimal(Double.valueOf(total_fee)/100).setScale(2,BigDecimal.ROUND_HALF_UP);
            List<Long> orderIds = new ArrayList<Long>();
            for(String orderIdStr:pay.getOrderIds().split("_")){
                orderIds.add(Long.valueOf(orderIdStr));
            }
            if(ListUtil.isNull(orderIds)){
                logger.error("支付-微信-回掉-本地预支付记录无订单参数，返回");

                return "fail";
            }
            param.clear();
            //1.0,校验预支付的订单金额是否和本次支付相同
            Double sundayPayAmount=0.00;
            for(SundayPay sundayPay:sundayPays){
                sundayPayAmount+=sundayPay.getPayAmount().doubleValue();
            }
            if(paidAmount.compareTo(new BigDecimal(sundayPayAmount).setScale(2,BigDecimal.ROUND_HALF_UP))==-1){
                logger.error("支付-微信-回掉-本地预支付金额和实际回掉金额有误-此操作标识有人非法刷单，本地预支付金额="+sundayPayAmount+",微信回掉金额="+paidAmount);
                return "fail";
            }

            //2.0,校验订单订单金额是否和本次支付相同。由于搜鸟私厨存在预付单据。暂时不校验。待确认预付需求再完成
            Double orderPayAmount = 0.00;
            param.clear();
            param.put("ids",orderIds);
            List<CooOrder> orders =orderMapper.select(param);
            for(CooOrder order:orders){
                orderPayAmount+=order.getPayAmount().doubleValue();
            }
            if(paidAmount.compareTo(new BigDecimal(orderPayAmount).setScale(2,BigDecimal.ROUND_HALF_UP))==-1){
                logger.error("支付-微信-回掉-本地订单实付金额和实际回掉金额有误-此操作标识有人非法刷单，本地订单实付金额="+orderPayAmount+",微信回掉金额="+paidAmount);
                return "fail";
            }
            //3.0修改订单状态

            for(CooOrder order:orders){
                if (order.getOrderStatus() == SundayCommonConstants.ORDER_STATUS_DFK) {
                    logger.info("支付-微信-回掉-当前支付订单"+order.getOrderNo());
                    order.setOrderStatus(SundayCommonConstants.ORDER_STATUS_DPS);
                    order.setPayTime(new Date());
                    order.setPayNo(trade_no);
                    order.setPayType(SundayCommonConstants.pay_type_wechatpay_html);
                    orderMapper.update(order);
                    //减库存
                    param.clear();
                    param.put("orderId",order.getId());
                    List<CooOrderProduct> orderProducts=orderProductMapper.select(param);
                    if(ListUtil.isNotNull(orderProducts)){
                        CooOrderProduct orderProduct=orderProducts.get(0);
                        //减库存
                        SundayProduct product=productService.find(orderProduct.getProductId());
                        product.setStore(product.getStore()-orderProduct.getNum());
                        productService.update(product);
                    }
                }
            }
            Long walletRecordId=0l;

        for(String walletRecordIdStr:pay.getChargeIds().split("_")){
            walletRecordId=Long.valueOf(walletRecordIdStr);
            break;
        }
        CooWalletRecord walletRecord=walletRecordMapper.find(walletRecordId);

        walletRecord.setAmount(walletRecord.getAmount().multiply(new BigDecimal("1000000")));
        walletService.charge_callback(walletRecord,"充值消费-微信付款-支付编号"+trade_no);


        return callback_wechat_msg;
    }


}
